feat(todo): give sessions a durable plan - #17
Merged
Conversation
The `todo` tool tracks a session's plan in the store (schema v8), not the model's context window, so it survives crashes, resumes, and future compaction like everything else. Two choices carry the design, both house patterns from the pen: - Deterministic item ids (uuidv5 of session + call_id + index) make a replayed `add` converge on the same rows instead of duplicating them, so the whole tool is replay-safe. - The store owns the one-active-item invariant: marking an item in_progress returns any other active item to pending, in the same transaction. Items resolve by id prefix, mirroring session resolution. Every action returns the rendered plan, so the model always acts on current state. docs/TOOLS.md maps the rest of a best-in-class tool catalog onto the durability contract and sequences what comes next (job, pen worktree isolation, ask, hashline edits, ast-grep, ...). Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KoSjfcJPjXpkVLTS2Vxwwr
The pen's `agent` tool gains the two flags that complete the durable multi-agent story, plus the coordination plane to drive them: - `worktree: true` runs a work child in its own git worktree on its own `bullpen/<child-id>` branch — the CLI's `--bg --worktree` behavior, now available per child. Placement mirrors the CLI resume path (record before create; locate decides on replay), so a replayed spawn reattaches to the same tree. Isolated children get a sandbox rebased onto their worktree with the linked-worktree git dirs widened in. Worktrees follow the store's directory, so isolated stores (tests, $BULLPEN_HOME) keep their worktrees beside their database. - `background: true` dispatches the child and returns immediately. The child runs in this process but coordinates through the store like everything else, so crashes leave the same recoverable state as any session. Cancellation is cooperative — a oneshot into the child's select loop — so a cancelled child records its own terminal state. - The `job` tool exposes the coordination plane to the model: `list` derives each child's state from stored status plus pid liveness, `wait` polls the store to a terminal state and returns the child's recorded answer, `cancel` signals a background child, which finishes as failed and stays resumable. Inspect, isolated, and background children are all parallel-safe; only a work child in the shared checkout stays serial. Plumbing: `pid_alive` moves from the CLI into `store::status` and the worktree module moves from the CLI into the harness, so both sides of the coordination plane share one definition of liveness and placement. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KoSjfcJPjXpkVLTS2Vxwwr
The `ask` tool puts one structured question to the human driving the run. It is transport-agnostic: the application injects an `Asker`, and the CLI's implementation prints to stderr — never into the answer stream on stdout — and reads one line from the terminal on a blocking thread. Options render as a numbered list, and the tool owns the number-to-option mapping so every transport gets it identically. A run with nobody on the other end (background, `--json`, piped stdin) registers the *detached* variant: the model still sees the tool, and a call fails immediately with the reason — decide and note the assumption — instead of blocking on input nobody will ever type, or surfacing a bare unknown-tool error. Also folds the new coordination surface into the README and marks the coordination tranche done in docs/TOOLS.md. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KoSjfcJPjXpkVLTS2Vxwwr
`read_file` output becomes `line#hash<TAB>content`: every line carries an anchor made of its position plus the first four hex chars of its SHA-256. `edit_file` keeps the exact-string mode and gains a `patch` mode addressed by those anchors — hunks of replace / insert_after / delete, spans via an inclusive `to`, anchor "0" to prepend at the top, several hunks per call applied bottom-up with overlaps rejected. An anchor is a claim about content, not just a position, which is what makes edits against a drifted file safe: - a *moved* line (hash found on exactly one line) is followed there and reported, instead of patching whatever now sits at the old number; - a *changed* line (hash on zero or several lines) fails the call with fresh hashline context around the site, so the model re-anchors without another read — and never misapplies the edit. Recovery trusts a hash only when it is unique in the file, so a four-hex-char collision degrades to an explicit error, never a wrong edit. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KoSjfcJPjXpkVLTS2Vxwwr
`read_file` now reads whatever the path names. A directory renders a sorted listing — directories first, sizes for files — instead of a bare OS error. An http(s) URL is fetched with GET, the body bounded while it streams (2 MiB) rather than after it lands, with the status carried in the output and a non-success status carried in the error. The sandbox's network capability governs URL reads exactly as it governs shell commands: a sandbox that denies network refuses the fetch outright. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KoSjfcJPjXpkVLTS2Vxwwr
ARCHITECTURE's crate table, the parallel-scheduling note, the harness module docs, and the README status row all predate the coordination and hashline work; bring each in line with what actually ships. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KoSjfcJPjXpkVLTS2Vxwwr
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (20)
📝 WalkthroughWalkthroughThe change adds hashline file operations, durable session todos, child job coordination, worktree and background execution, process-liveness sharing, and interactive question handling. It also updates CLI registration, crate exports, dependencies, tests, and documentation. ChangesTools and execution
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant Agent
participant PenTool
participant Store
participant JobTool
participant ChildSession
Agent->>PenTool: dispatch work child
PenTool->>Store: create or recover child session
PenTool->>ChildSession: start worktree or background execution
ChildSession->>Store: record completion or failure
Agent->>JobTool: list or wait
JobTool->>Store: read child state
JobTool->>ChildSession: wait for or cancel local child
JobTool-->>Agent: return status or report
Possibly related PRs
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The
todotool tracks a session's plan in the store (schema v8), not themodel's context window, so it survives crashes, resumes, and future
compaction like everything else.
Two choices carry the design, both house patterns from the pen:
replayed
addconverge on the same rows instead of duplicating them,so the whole tool is replay-safe.
in_progress returns any other active item to pending, in the same
transaction. Items resolve by id prefix, mirroring session resolution.
Every action returns the rendered plan, so the model always acts on
current state. docs/TOOLS.md maps the rest of a best-in-class tool
catalog onto the durability contract and sequences what comes next
(job, pen worktree isolation, ask, hashline edits, ast-grep, ...).
Co-Authored-By: Claude noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01KoSjfcJPjXpkVLTS2Vxwwr
Summary by CodeRabbit